﻿using System;
using System.Linq;
using System.Windows;
using System.Windows.Input;
using WickedFlame.Core;
using WickedFlame.Core.History;
using WickedFlame.Core.Shapes;
using WickedFlame.Core.Tools;
using WickedFlame.Util.Actions;
using WickedFlame.Util.Events;
using WickedFlame.VecDraw.Dialog;
using WickedFlame.VecDraw.VecApp;
using WickedFlame.VecDraw.Base.Controls;
using WickedFlame.VecDraw.viewmodels;
using WickedFlame.Util;
using WickedFlame.VecDraw.Base.mvvm.common;

namespace WickedFlame.VecDraw
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
	public partial class MainGui : WindowExt, ICanvasContainer
    {
        public MainGui()
        {
            InitializeComponent();

			// register a refernece of this instance to the ServiceLocator for the mvvm pattern
			ServiceLocator.RegisterGlobalService<ICanvasContainer>(this);

            // register tools to the canvas
            RegisterTools();
        }

        #region Implementation

        private void OnLoaded(object sender, RoutedEventArgs e)
        {
            CreateNewCanvas(600, 400);

            canvasManager.Focus();

            this.Focus();

            loaded = true;
            if (!string.IsNullOrEmpty(loadFileName))
                ImportFile(loadFileName);
        }

        private void OnClosing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            //TODO:
            //check if all canvases are saved
        }

        string loadFileName = string.Empty;
        bool loaded = false;

        public bool ImportFile(string path)
        {
            if (loaded)
            {
                var action = new ImportFromFileAction();
                action.DoAction(this, path);
                if (!action.Error)
                {
                    canvasManager.Add(action.Image);
                }
                else
                    return false; // error occured
            }
            else
                loadFileName = path;

            return true;
        }

        /// <summary>
        /// registers the drawing tools in the canvas
        /// </summary>
        private void RegisterTools()
        {
            DrawingCanvas.ToolsControler.Add(new SelectionTool());
            DrawingCanvas.ToolsControler.Add(new TrackerSelectionTool());
            DrawingCanvas.ToolsControler.Add(new HardSelectionTool());

            DrawingCanvas.ToolsControler.Add(new RectangleTool());
            DrawingCanvas.ToolsControler.Add(new EllipseTool());
            DrawingCanvas.ToolsControler.Add(new PolygonTool());
            DrawingCanvas.ToolsControler.Add(new LineTool());
            DrawingCanvas.ToolsControler.Add(new SCurveTool());
            DrawingCanvas.ToolsControler.Add(new CurveTool());
            DrawingCanvas.ToolsControler.Add(new TextTool());
            DrawingCanvas.ToolsControler.Add(new ColorPickerTool(this));

            //DrawingCanvas.ToolsControler.Add(new RectangleTool(typeof(DrawingCanvas)));

            DrawingCanvas.ToolsControler.ToolType = typeof(SelectionTool);
        }

        private void UpdateTitle()
        {
            string title = "";
            if (canvasManager.SelectedItem != null)
            {
                if (string.IsNullOrEmpty(canvasManager.SelectedImage.FileName))
                    title += "Untitled";
                else
                {
                    try
                    {
                        title += canvasManager.SelectedImage.FileName.Substring(canvasManager.SelectedImage.FileName.LastIndexOf("\\") + 1);
                    }
                    catch
                    {
                        title += canvasManager.SelectedImage.FileName;
                    }
                }
                title += " (" + canvasManager.SelectedCanvas.Zoom + "%)";
            }

            this.Title = title;
        }

        #endregion

        #region Events

		#region ICanvasContainer Members
		
		public void CreateNewCanvas(double width, double height, bool addLayer = true)
        {
            canvasManager.Add(width, height, addLayer);

            //register tools to the canvas
            DrawingCanvas.ToolsControler.ToolType = typeof(SelectionTool);

            UpdateTitle();
        }

		public void Add(VectorImage image)
		{
			canvasManager.Add(image);
		}

		public void Add(DrawingCanvas canvas)
		{
			canvasManager.Add(canvas);
		}

		public void ResizeCanvas(double width, double height)
		{
			canvasManager.ResizeCanvas(width, height);
		}

		public void ZoomIn(int percent)
		{
			canvasManager.ZoomIn(percent);
		}

		public void ZoomOut(int percent)
		{
			canvasManager.ZoomOut(percent);
		}

    	#endregion

		private void Canvas_OnZoomChanged(object sender, ZoomChangedEventArgs e)
        {
            UpdateTitle();
        }

        private void canvasManager_CanvasChanged(object sender, EventArgs e)
        {
			var dc = DataContext as MainWindowViewModel;
			if (dc != null)
				dc.PageSize = string.Format("{0} x {1}", canvasManager.SelectedCanvas.Width, canvasManager.SelectedCanvas.Height);

            UpdateTitle();
        }

        private void DockPanel_MouseMove(object sender, MouseEventArgs e)
        {
			var dc = DataContext as MainWindowViewModel;
			if (dc == null)
				return;

            var p = new Point(Mouse.GetPosition(canvasManager.SelectedCanvas).X, Mouse.GetPosition(canvasManager.SelectedCanvas).Y);
            dc.MousePosition = string.Format("{0}, {1}",(int)p.X,(int)p.Y);
        }

        private void Canvas_OnDrop(object sender, DragEventArgs e)
        {
            if (!e.Handled)
            {
                Array a = (Array)e.Data.GetData(DataFormats.FileDrop);
                if (a != null)
                {
                    var fda = new DropAction();
                    fda.DoAction(canvasManager.SelectedCanvas, a.GetValue(0).ToString());

                    if (canvasManager.SelectedCanvas == null)
                    {
                        CreateNewCanvas(fda.Width, fda.Height, false);
                        fda.Canvas = canvasManager.SelectedCanvas;
                        fda.FinalilzeAction();
                    }
                    else
                    {
                        var dlg = new ImageDragDropDialog();
                        dlg.Owner = this;
                        dlg.WindowStartupLocation = WindowStartupLocation.CenterOwner;
                        if (dlg.ShowDialog() == true)
                        {
                            if (dlg.DragDropDialogResult == DragDropDialogResult.Open)
                            {
                                CreateNewCanvas(fda.Width, fda.Height);
                                fda.Canvas = canvasManager.SelectedCanvas;
                            }

                            //create the shape and add to the canvas
                            fda.FinalilzeAction();
                        }
                    }

                    e.Handled = true;
                }
            }
        }

        private void Canvas_OnMouseWheel(object sender, MouseWheelEventArgs e)
        {
            if (canvasManager != null && canvasManager.SelectedCanvas != null)
            {
                if (Keyboard.IsKeyDown(Key.LeftCtrl) ||
                    Keyboard.IsKeyDown(Key.RightCtrl))
                {
                    if (e.Delta > 0)
                    {
                        //up
                        ZoomIn(5);
                    }
                    else
                    {
                        //down
                        ZoomOut(5);
                    }
                }
            }
        }

        #endregion

        #region Commands

        private void ShapeCommandExecuted(object sender, ExecutedRoutedEventArgs e)
        {
            if (e.Command == ShapeCommands.CloseShape && !e.Handled)
            {
                //var command = new PropertyChangedCommand(canvasManager.SelectedCanvas.SelectedLayer.ShapeList, canvasManager.SelectedCanvas.SelectedLayerIndex);
                var command = new PolygonClosedCommand(canvasManager.SelectedCanvas.SelectedLayer.ShapeList, canvasManager.SelectedCanvas.SelectedLayerIndex);
                
                var s = canvasManager.SelectedCanvas.SelectedLayer.ShapeList.Selection.First() as PolygonShape;

                s.JoinEndSegments = true;

                command.SetNewState();
                canvasManager.SelectedCanvas.PushHistoryCommand(command);

                DrawingCanvas.DrawTrackers();
            }
            else if (e.Command == ShapeCommands.CombineShapesCommand && !e.Handled)
            {
                var action = new CombineShapeAction();
                if (!action.DoAction((canvasManager.SelectedCanvas)))
                {
                    MessageBox.Show(
                        this,
                        "To be able to join segments \ntwo segments have to be selected with each one end highlited.",
                        "Invalid selection",
                        MessageBoxButton.OK,
                        MessageBoxImage.Information);
                }

                e.Handled = true;
            }
        }

        private void ShapeCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            if (e.Command == ShapeCommands.CloseShape)
            {
                if (canvasManager != null &&
                    canvasManager.SelectedItem != null &&
                    canvasManager.SelectedCanvas.SelectedLayer.ShapeList.SelectionCount == 1 &&
                    canvasManager.SelectedCanvas.SelectedLayer.ShapeList.Selection.First() is PolygonShape &&
                    !(canvasManager.SelectedCanvas.SelectedLayer.ShapeList.Selection.First() as PolygonShape).JoinEndSegments)
                {
                    e.CanExecute = true;
                }
                else
                    e.CanExecute = false;
                e.Handled = true;
            }
            if (e.Command == ShapeCommands.CombineShapesCommand && !e.Handled)
            {
                if (canvasManager == null ||
                    canvasManager.SelectedItem == null ||
                    (canvasManager.SelectedCanvas.SelectedLayer.ShapeList.SelectionCount <= 0
                    && DrawingCanvas.ToolsControler.ToolType != typeof(TrackerSelectionTool)))
                {
                    e.CanExecute = false;
                    e.Handled = true;
                }
            }

            if (!e.Handled)
                e.CanExecute = true;
        }

        private void CommandExecuted(object sender, ExecutedRoutedEventArgs e)
        {
			
            if (e.Command == MainMenuCustomCommands.ToPolygonCommand && !e.Handled)
            {
                if (canvasManager.SelectedCanvas.SelectedLayer.ShapeList.SelectionCount >= 1)
                {
                    var action = new ConvertShapeToPolygonAction();
                    action.DoAction(canvasManager.SelectedCanvas);
                }
            }
            else if (e.Command == MainMenuCustomCommands.CombineImagesCommand && !e.Handled)
            {
                var action = new MergeImagesAction();
                action.DoAction(canvasManager.SelectedCanvas);
                e.Handled = true;
            }
            else if (e.Command == MainMenuCustomCommands.ToImageCommand && !e.Handled)
            {
                var action = new ConvertShapeToImageAction();
                action.DoAction(canvasManager.SelectedCanvas);
                e.Handled = true;
            }
            else if (e.Command == MainMenuCustomCommands.ExitCommand)
            {
                this.Close();
            }
			

            UpdateTitle();
        }

        private void CommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
        {

            if (e.Command == MainMenuCustomCommands.ToPolygonCommand && !e.Handled)
            {
                if (canvasManager == null ||
                    canvasManager.SelectedCanvas == null ||
                    canvasManager.SelectedCanvas.SelectedLayer.ShapeList.SelectionCount <= 0)
                {
                    e.CanExecute = false;
                    e.Handled = true;
                }
            }
			
            if (e.Command == MainMenuCustomCommands.CombineImagesCommand && !e.Handled)
            {
                if (canvasManager == null ||
                    canvasManager.SelectedCanvas == null ||
                    canvasManager.SelectedCanvas.SelectedLayer.ShapeList.SelectionCount <= 0)
                {
                    e.CanExecute = false;
                    e.Handled = true;
                }
            }
            if (e.Command == MainMenuCustomCommands.ToImageCommand && !e.Handled)
            {
                if (canvasManager == null ||
                    canvasManager.SelectedCanvas == null ||
                    canvasManager.SelectedCanvas.SelectedLayer.ShapeList.SelectionCount <= 0)
                {
                    e.CanExecute = false;
                    e.Handled = true;
                }
            }
			
            if (!e.Handled)
                e.CanExecute = true;
        }

        #endregion

	}
}
